<template>
    <div class="App">
        <!-- 参数 -->
        <a-space direction="vertical" :size="2" class="args">
            <a-button
                type="primary"
                style="width: 100%"
                size="small"
                @click="actions.clickResetArgs"
                >{{ $t('Reset Paramters') }}</a-button
            >
            <a-space style="margin-top: 3px">
                <span>{{ $t('Language') }}:</span>
                <a-select
                    style="width: 100px"
                    size="small"
                    v-model:value="state.lang"
                    @change="actions.changeLang"
                >
                    <a-select-option :value="ENUM_LANG.en">{{ $t('English') }}</a-select-option>
                    <a-select-option :value="ENUM_LANG.zh_cn">{{ $t('Chinese') }}</a-select-option>
                </a-select>
            </a-space>
            <a-space>
                <span>mkbitmap: {{ $t('Enable Preprocessing') }}</span>
                <a-switch v-model:checked="state.input.mkbitmapEnable" />
            </a-space>
            <h3>potrace: {{ $t('Paramters') }}</h3>
            <!-- 参数: potrace -->
            <a-space v-for="arg in state.input.potraceArgs" :size="10">
                <a-tooltip placement="right">
                    <template #title>
                        <div>
                            <p>{{ arg.desc }} </p>
                        </div>
                    </template>
                    <a-space :size="0" style="width: 120px">
                        <span>{{ arg.name }}</span>
                        <span v-if="typeof arg.value === 'number'"
                            >{{ '(' + arg.value + ')' }}
                        </span>
                    </a-space>
                </a-tooltip>
                <a-checkbox v-if="typeof arg.value === 'boolean'" v-model:checked="arg.value" />
                <a-slider
                    v-if="typeof arg.value === 'number'"
                    :tooltipOpen="false"
                    class="props"
                    v-model:value="arg.value"
                    :min="arg.min"
                    :max="arg.max"
                    :step="arg.step > 0 ? arg.step : 0.01"
                />
                <a-select
                    class="props"
                    v-if="typeof arg.value === 'string'"
                    v-model:value="arg.value"
                    :options="arg.valueOptions"
                ></a-select>
            </a-space>
            <h3 v-if="state.input.mkbitmapEnable">mkbitmap: {{ $t('Paramters') }}</h3>
            <a-space
                v-if="state.input.mkbitmapEnable"
                v-for="arg in state.input.mkbitmapArgs"
                :size="10"
            >
                <a-tooltip placement="right">
                    <template #title>
                        <div>
                            <p>{{ arg.desc }} </p>
                        </div>
                    </template>
                    <a-space :size="0" style="width: 120px">
                        <span>{{ arg.name }}</span>
                        <span v-if="typeof arg.value === 'number'"
                            >{{ '(' + arg.value + ')' }}
                        </span>
                    </a-space>
                </a-tooltip>
                <a-checkbox v-if="typeof arg.value === 'boolean'" v-model:checked="arg.value" />
                <a-slider
                    v-if="typeof arg.value === 'number'"
                    :tooltipOpen="false"
                    class="props"
                    v-model:value="arg.value"
                    :min="arg.min"
                    :max="arg.max"
                    :step="arg.step > 0 ? arg.step : 0.01"
                />
                <a-select
                    class="props"
                    v-if="typeof arg.value === 'string'"
                    v-model:value="arg.value"
                    :options="arg.valueOptions"
                ></a-select>
            </a-space>
        </a-space>
        <!-- 输入图片 -->
        <div class="container-img">
            <div class="header">
                <!-- 上传图片 -->
                <a-button type="primary" size="small" @click="actions.clickUploadImage">{{
                    $t('Upload Picture')
                }}</a-button>
                <a-space :size="10">
                    <span>{{ $t('Use Picture') }}</span>
                    <a-select
                        style="width: 200px"
                        v-model:value="state.input.imgUrl"
                        :options="_optionsImg"
                    ></a-select>
                </a-space>

                <a-button type="primary" size="small" @click="actions.clickConvert">{{
                    $t('Start Conversion')
                }}</a-button>
                <!-- 不可见的 input -->
                <input
                    ref="elInputAddFile"
                    type="file"
                    accept=".png,.jpg,.jpeg"
                    :style="{ display: 'none' }"
                    multiple="{false}"
                    @change="actions.changeImageFile"
                />
            </div>
            <img v-if="state.input.imgUrl" class="img" :src="state.input.imgUrl" />
        </div>
        <!-- 输出图片 -->
        <div class="container-img">
            <div class="header">
                <a-button
                    type="primary"
                    size="small"
                    style="width: 75px"
                    @click="actions.clickDownloadSvg"
                    >{{ $t('Download') }}</a-button
                >
                <!-- <span>Socket: {{ state.connected ? $t('Connected') : $t('Disonnected') }}</span> -->
                <span>{{ 'v' + version }}</span>
                <!-- <span>dev by 切片软件部-刘明（有问题请联系我）</span> -->
            </div>
            <img v-if="state.output.svgBase64" class="img" :src="state.output.svgBase64" />
        </div>
    </div>
</template>

<script setup>
    import { reactive, ref, onMounted } from 'vue';
    import socketManager from './socketManager.js';
    import { message } from 'ant-design-vue';
    import { saveAs } from 'file-saver';
    import _mkbitmapArgs_en from './_mkbitmapArgs_en.json';
    import _mkbitmapArgs_zh_cn from './_mkbitmapArgs_zh_cn.json';
    import _potraceArgs_en from './_potraceArgs_en.json';
    import _potraceArgs_zh_cn from './_potraceArgs_zh_cn.json';
    import _optionsImg from './_optionsImg.json';
    import { version } from '../package.json';
    import { useI18n } from 'vue-i18n';
    const { locale } = useI18n();

    const elInputAddFile = ref();

    async function downloadAndConvertToBase64(imgUrl) {
        try {
            const response = await fetch(imgUrl);
            const blob = await response.blob();

            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onloadend = () => resolve(reader.result.split(',')[1]); // 去掉 data:image/png;base64, 部分
                reader.onerror = reject;
                reader.readAsDataURL(blob);
            });
        } catch (error) {
            console.error('Error downloading image:', error);
            return null;
        }
    }

    function svgToBase64(svgString) {
        return 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgString)));
    }

    const ENUM_LANG = {
        en: 'en',
        zh_cn: 'zh_cn'
    };

    const state = reactive({
        connected: false, // socket 状态：断开，已连接
        output: {
            svgStr: '',
            svgBase64: ''
        },
        input: {
            imgUrl: './images/cat.jpg',
            mkbitmapEnable: false,
            potraceArgs: JSON.parse(JSON.stringify(_potraceArgs_en)),
            mkbitmapArgs: JSON.parse(JSON.stringify(_mkbitmapArgs_en))
        },
        lang: ENUM_LANG.en
    });

    onMounted(() => {
        // window.serverAddress = 'http://172.20.40.143:9000';

        window.serverAddress = window.serverAddress
            ? window.serverAddress
            : 'http://localhost:9000';

        socketManager.init(
            window.serverAddress,
            () => {
                // connect
                state.connected = true;
            },
            () => {
                // disconnect
                state.connected = false;
            }
        );
    });

    const argsToArr = (args) => {
        const arr = [];
        args.forEach((arg) => {
            const { cmd, value } = arg;
            switch (typeof value) {
                case 'string':
                case 'number':
                    // 为了解决 fillecolor 参数问题，使用 null
                    if (value !== 'null') {
                        arr.push(`--${cmd}`);
                        arr.push(`${value}`);
                    }
                    break;
                case 'boolean':
                    value && arr.push(`--${cmd}`);
                    break;
            }
        });
        return arr;
    };

    const actions = {
        changeLang(value) {
            locale.value = value;

            switch (value) {
                case ENUM_LANG.en:
                    state.input.potraceArgs = JSON.parse(JSON.stringify(_potraceArgs_en));
                    state.input.mkbitmapArgs = JSON.parse(JSON.stringify(_mkbitmapArgs_en));
                    break;
                case ENUM_LANG.zh_cn:
                    state.input.potraceArgs = JSON.parse(JSON.stringify(_potraceArgs_zh_cn));
                    state.input.mkbitmapArgs = JSON.parse(JSON.stringify(_mkbitmapArgs_zh_cn));
                    break;
            }
        },
        clickResetArgs() {
            actions.changeLang(state.lang);
        },
        clickConvert: async () => {
            // 准备参数
            const mkbitmapEnable = state.input.mkbitmapEnable;
            const potraceArgs = argsToArr(state.input.potraceArgs);
            const mkbitmapArgs = argsToArr(state.input.mkbitmapArgs);
            console.log('potraceArgs: ' + JSON.stringify(potraceArgs, null, 2));
            console.log('mkbitmapArgs: ' + JSON.stringify(mkbitmapArgs, null, 2));

            const eventName = 'bitmap2svg';
            const imgBase64 = await downloadAndConvertToBase64(state.input.imgUrl);
            const args = { imgBase64, mkbitmapArgs, potraceArgs, mkbitmapEnable };

            socketManager.emitWithAck(eventName, args, ({ success, msg, svgStr }) => {
                if (!success) {
                    message.error($t('SVG generated failed') + ': msg=' + msg);
                    return;
                }
                message.success($t('SVG generated successfully'));
                state.output.svgStr = svgStr;
                state.output.svgBase64 = svgToBase64(svgStr);
            });
        },
        clickDownloadSvg() {
            const blob = new Blob([state.output.svgStr], { type: 'image/svg+xml;charset=utf-8' });
            saveAs(blob, 'output.svg');
        },
        // 打开文件选择 dialog 并选择：文件
        clickUploadImage() {
            elInputAddFile.value.value = null;
            elInputAddFile.value.click();
        },
        changeImageFile(event) {
            const file = event.target.files[0];
            if (!file) {
                console.error('file is null');
                return;
            }
            state.input.imgUrl = URL.createObjectURL(file);
        }
    };
</script>

<style lang="scss" scoped>
    h3 {
        // color: white;
        margin: 10px 0 0 0;
    }

    h4 {
        color: white;
        margin: 0;
    }

    .App {
        width: 100%;
        height: 100%;
        background-color: #808080;
        padding: 5px;
        display: flex;
        box-sizing: border-box;

        .header {
            width: 100%;
            height: 40px;
            display: flex;
            box-sizing: border-box;
            justify-content: space-between;
            align-items: center;
            border: 1px solid #e9e9e9;
            padding: 5px;
            margin-bottom: 5px;
        }

        .args {
            height: 100%;
            width: 300px;
            border: 1px solid #e9e9e9;
            padding: 5px;
            overflow-y: auto;
        }

        .container-img {
            height: 100%;
            flex: 1;
            border: 1px solid #e9e9e9;
            padding: 5px;
            display: flex;
            flex-direction: column;
            overflow-y: auto;

            .child {
                width: 100%;
                flex: 1;
                border: 1px solid #e9e9e9;
            }
        }

        .btn-convert {
            height: 40px;
            width: 100px;
        }

        .img {
            height: auto;
            width: 100%;
            border: 1px solid #e9e9e9;
        }

        .connect {
            position: absolute;
            top: 10px;
            right: 10px;
            z-index: 99;
            background-color: antiquewhite;
            padding: 5px;
        }

        .props {
            width: 150px;
        }
    }
</style>
